home *** CD-ROM | disk | FTP | other *** search
/ Linux Cubed Series 3: Developer Tools / Linux Cubed Series 3 - Developer Tools.iso / utils / file / managers / mc-3.2 / mc-3 / mc-3.2.1 / src / wtools.c < prev    next >
Encoding:
C/C++ Source or Header  |  1996-05-17  |  14.4 KB  |  629 lines

  1.  
  2. /* {{{  */
  3.  
  4. /* {{{ Copyright Notice */
  5.  
  6. /* Widget based utility functions.
  7.    Copyright (C) 1994, 1995 the Free Software Foundation
  8.    
  9.    Authors: 1994, 1995 Miguel de Icaza
  10.             1994, 1995 Radek Doulik
  11.         1995  Jakub Jelinek
  12.  
  13.    This program is free software; you can redistribute it and/or modify
  14.    it under the terms of the GNU General Public License as published by
  15.    the Free Software Foundation; either version 2 of the License, or
  16.    (at your option) any later version.
  17.  
  18.    This program is distributed in the hope that it will be useful,
  19.    but WITHOUT ANY WARRANTY; without even the implied warranty of
  20.    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  21.    GNU General Public License for more details.
  22.  
  23.    You should have received a copy of the GNU General Public License
  24.    along with this program; if not, write to the Free Software
  25.    Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
  26.  
  27.  */
  28.  
  29. /* }}} */
  30.  
  31. /*  [] = "$Id: wtools.c,v 1.3 1995/02/21 19:07:51 miguel Exp $" */
  32.  
  33. #include <config.h>
  34. #include <string.h>
  35. #include <stdio.h>
  36. #include <malloc.h>
  37. #include "tty.h"
  38. #include <stdarg.h>
  39. #include "mad.h"
  40. #include "global.h"
  41. #include "util.h"
  42. #include "win.h"
  43. #include "color.h"
  44. #include "mouse.h"
  45. #include "dlg.h"
  46. #include "widget.h"
  47. #include "menu.h"
  48. #include "wtools.h"
  49. #include "key.h"    /* For mi_getch() */
  50. #include "dialog.h"    /* For do_refresh() and my_wputs() */
  51. #include "complete.h"   /* INPUT_COMPLETE_CD */
  52.  
  53. /* }}} */
  54.  
  55. /* {{{ Listbox utility functions */
  56.  
  57. void listbox_refresh (Dlg_head *h)
  58. {
  59.     /* Draw the screen */
  60.     attrset (COLOR_NORMAL);
  61.     dlg_erase (h);
  62.     draw_box (h, 1, 1, h->lines - 2, h->cols - 2);
  63.     attrset (COLOR_HOT_NORMAL);
  64.     dlg_move (h, 1, (h->cols-strlen (h->title))/2);
  65.     printw ("%s", h->title);
  66. }
  67.  
  68. static int listbox_callback (Dlg_head *h, int id, int msg)
  69. {
  70.     switch (msg) {
  71.     case DLG_DRAW:
  72. #ifndef HAVE_X
  73.         listbox_refresh(h);
  74. #endif
  75.         return 1;
  76.     }
  77.     return 0;
  78. }
  79.  
  80. Listbox *create_listbox_window (int cols, int lines, char *title, char *help)
  81. {
  82.     int xpos, ypos;
  83.     Listbox  *listbox = xmalloc (sizeof (Listbox), "create_listbox_window");
  84.  
  85.     /* Adjust sizes */
  86.     lines = (lines > LINES-6) ? lines = LINES - 6 : lines;
  87.     cols = cols > COLS-6 ? COLS - 6 : cols;
  88.  
  89.     /* I'm not sure if this -2 is safe, should test it */
  90.     xpos = (COLS-cols)/2;
  91.     ypos = (LINES-lines)/2 - 2;
  92.  
  93.     /* Create components */
  94.     listbox->dlg = create_dlg (ypos, xpos, lines+6, cols+4, dialog_colors,
  95.                    listbox_callback, help, "listbox", DLG_CENTER);
  96.     x_set_dialog_title (listbox->dlg, title);           
  97.     
  98.     listbox->list = listbox_new (2, 2, cols, lines, listbox_finish, 0);
  99.  
  100.     add_widget (listbox->dlg,
  101.     button_new (lines+3, (cols/2)-5, B_CANCEL, "[ Cancel ]",'c',2,0, 0));
  102.     add_widget (listbox->dlg, listbox->list);
  103. #ifndef HAVE_X
  104.     listbox_refresh(listbox->dlg);
  105. #endif /* !HAVE_X */
  106.     return listbox;
  107. }
  108.  
  109. /* Returns the number of the item selected */
  110. int run_listbox (Listbox *l)
  111. {
  112.     int val;
  113.     
  114.     run_dlg (l->dlg);
  115.     if (l->dlg->ret_value == B_CANCEL)
  116.     val = -1;
  117.     else
  118.     val = l->list->pos;
  119.     destroy_dlg (l->dlg);
  120.     free (l);
  121.     return val;
  122. }
  123.  
  124. /* }}} */
  125.  
  126.  
  127. /* {{{ Query Dialog functions */
  128.  
  129. struct text_struct {
  130.     char *text;
  131.     char *header;
  132. };
  133.  
  134. static int query_callback (struct Dlg_head *h, int Id, int Msg)
  135. {
  136.     struct text_struct *info;
  137.  
  138.     info = (struct text_struct *) h->data;
  139.     
  140.     switch (Msg){
  141. #ifndef HAVE_X    
  142.     case DLG_DRAW:
  143.     /* designate window */
  144.     attrset (NORMALC);
  145.     dlg_erase (h);
  146.     draw_box (h, 1, 1, h->lines-2, h->cols-2);
  147.     dlg_move (h, 1, (h->cols-strlen (info->header))/2);
  148.     printw ("%s", info->header);
  149.     break;
  150. #endif
  151.     }
  152.     return 0;
  153. }
  154.  
  155.  
  156. Dlg_head *last_query_dlg;
  157.  
  158. static int sel_pos = 0;
  159.  
  160. /* Used to ask questions to the user */
  161. int query_dialog (char *header, char *text, int flags, int count, ...)
  162. {
  163.     va_list ap;
  164.     Dlg_head *query_dlg;
  165.     int win_len = 0;
  166.     int i;
  167.     int result = -1;
  168.     int xpos, ypos;
  169.     int cols, lines;
  170.     char *cur_name;
  171.     static int query_colors [4];
  172.     static struct text_struct pass;
  173. #ifdef HAVE_X    
  174.     static char *buttonnames [10];
  175. #endif
  176.     
  177.     /* set dialog colors */
  178.     query_colors [1] = (flags & D_ERROR) ? REVERSE_COLOR : Q_SELECTED_COLOR;
  179.     query_colors [0] = (flags & D_ERROR) ? ERROR_COLOR : Q_UNSELECTED_COLOR;
  180.     
  181.     if (count > 0){
  182.     va_start (ap, count);
  183.     for (i = 0; i < count; i++)
  184.         win_len += strlen (va_arg (ap, char *)) + 2;
  185.     va_end (ap);
  186.     }
  187.  
  188.     /* count coordinates */
  189.     cols = 6 + max (win_len+1, max (strlen (header), msglen (text, &lines)));
  190.     lines += 4 + (count > 0 ? 2 : 0);
  191.     xpos = COLS/2 - cols/2;
  192.     ypos = LINES/3 - (lines-3)/2;
  193.     pass.header = header;
  194.     pass.text   = text;
  195.  
  196.     /* prepare dialog */
  197.     query_dlg = create_dlg (ypos, xpos, lines, cols, query_colors,
  198.                 query_callback, "[QueryBox]", "query", DLG_NONE);
  199.     x_set_dialog_title (query_dlg, header);
  200.  
  201.     /* The data we need to pass to the callback */
  202.     query_dlg->cols = cols; 
  203.     query_dlg->lines = lines; 
  204.     query_dlg->data  = &pass;
  205.     
  206.     query_dlg->direction = DIR_BACKWARD;
  207.  
  208.     if (count > 0){
  209.  
  210.     cols = (cols-win_len-2)/2 + 2;
  211.     va_start (ap, count);
  212.     for (i = 0; i < count; i++){
  213.         cur_name = va_arg (ap, char *);
  214.         xpos = strlen (cur_name)+2;
  215. #ifndef HAVE_XVIEW
  216.     if (flags & WITH_HOTKEYS)
  217.     add_widget (query_dlg, button_new
  218.             (lines-3, cols, B_USER+i, cur_name+1,
  219.              cur_name [0], -1, 0, 0));
  220.     else {
  221.     char *s = cur_name;
  222.  
  223.     while (*s == ' ')
  224.         s++;
  225.  
  226.     add_widget (query_dlg, button_new
  227.             (lines-3, cols, B_USER+i, cur_name,
  228.              *s, -1, 0, 0));
  229.     }
  230. #else             
  231.         buttonnames [i] = cur_name;
  232. #endif                 
  233.         cols += xpos;
  234.         if (i == sel_pos)
  235.             query_dlg->initfocus = query_dlg->current;
  236.     }
  237.     va_end (ap);
  238.  
  239. #ifdef HAVE_XVIEW
  240.         for (i = count - 1; i >= 0; i--) {
  241.         if (flags & WITH_HOTKEYS)
  242.         add_widgetl (query_dlg, button_new
  243.                 (0, 0, B_USER+i, buttonnames [i] + 1,
  244.                  *(buttonnames [i]), -1, 0, 0),
  245.                  i ? XV_WLAY_RIGHTOF : XV_WLAY_CENTERROW);
  246.         else
  247.         add_widgetl (query_dlg, button_new
  248.                 (0, 0, B_USER+i, buttonnames [i],
  249.                  *(buttonnames [i]), -1, 0, 0), 
  250.                  i ? XV_WLAY_RIGHTOF : XV_WLAY_CENTERROW);
  251.     }  
  252. #endif    
  253.     add_widget (query_dlg, label_new (2, 3, text));
  254.     
  255.     /* run dialog and make result */
  256.     run_dlg (query_dlg);
  257.     switch (query_dlg->ret_value){
  258.     case B_CANCEL:
  259.         break;
  260.     default:
  261.         result = query_dlg->ret_value-B_USER;
  262.     }
  263.  
  264.     /* free used memory */
  265.     destroy_dlg (query_dlg);
  266.     } else {
  267. #ifdef HAVE_X
  268.     add_widgetl (query_dlg, button_new(0, 0, B_EXIT, "OK", 0, -1, 0, 0),
  269.         XV_WLAY_CENTERROW);
  270.  
  271.     add_widget (query_dlg, label_new (2, 3, text));
  272. #ifdef HAVE_TK
  273.     if (flags & D_INSERT){
  274.     } else
  275. #endif
  276.     {
  277.         run_dlg (query_dlg);
  278.         destroy_dlg (query_dlg);
  279.     }
  280. #else
  281.     add_widget (query_dlg, label_new (2, 3, text));
  282.     add_widget (query_dlg, button_new(0, 0, 0, "", 0, -1, 0, 0));
  283. #endif /* HAVE_X */
  284.     last_query_dlg = query_dlg;
  285.     }
  286.     sel_pos = 0;
  287.     return result;
  288. }
  289.  
  290. void query_set_sel (int new_sel)
  291. {
  292.     sel_pos = new_sel;
  293. }
  294.  
  295. /* }}} */
  296.  
  297. /* {{{ The message function */
  298.  
  299. /* To show nice messages to the users */
  300. Dlg_head *message (int error, char *header, char *text, ...)
  301. {
  302.     va_list  args;
  303.     char     buffer [4096];
  304.     Dlg_head *d;
  305.  
  306.     /* Setup the display information */
  307.     strcpy (buffer, "\n");
  308.     va_start (args, text);
  309.     vsprintf (&buffer [1], text, args);
  310.     strcat (buffer, "\n");
  311.     va_end (args);
  312.     
  313.     query_dialog (header, buffer, error, 0);
  314. #ifndef HAVE_XVIEW
  315.     d = last_query_dlg;
  316. #ifdef HAVE_TK
  317.     if (error & D_INSERT){
  318.     init_dlg (d);
  319.     tk_dispatch_all ();
  320.     return d;
  321.     }
  322. #else    
  323.     init_dlg (d);
  324.     if (!(error & D_INSERT)){
  325.     mi_getch ();
  326.     dlg_run_done (d);
  327.     destroy_dlg (d);
  328.     } else
  329.     return d;
  330. #endif
  331. #endif    
  332.     return 0;
  333. }
  334.  
  335. /* }}} */
  336.  
  337. /* {{{ The chooser routines */
  338.  
  339. static int  remove_callback (int i, void *data)
  340. {
  341.     Chooser *c = (Chooser *) data;
  342.     
  343.     listbox_remove_current (c->listbox);
  344.  
  345.     dlg_select_widget (c->dialog, c->listbox);
  346.     dlg_select_nth_widget (c->dialog, 0);
  347.     
  348.     /* Return: do not abort dialog */
  349.     return 0;
  350. }
  351.  
  352. static int choose_callback (struct Dlg_head *h, int id, int Msg)
  353. {
  354.     switch (Msg){
  355. #ifndef HAVE_X    
  356.     case DLG_DRAW:
  357.     attrset (REVERSE_COLOR);
  358.     dlg_erase (h);
  359.     draw_box (h, 0, 0, h->lines, h->cols);
  360.     break;
  361. #endif    
  362.     }
  363.     return 0;
  364. }
  365.  
  366. Chooser *new_chooser (int lines, int cols, char *help, int flags)
  367. {
  368.     Chooser  *c;
  369.     int      button_lines;
  370.  
  371.     c = (Chooser *) xmalloc (sizeof (Chooser), "new_chooser");
  372.     c->dialog = create_dlg (0, 0, lines, cols, dialog_colors, choose_callback,
  373.                 help, "chooser", DLG_CENTER);
  374.     
  375.     c->dialog->lines = lines;
  376.     c->dialog->cols  = cols;
  377.     
  378.     button_lines = flags & CHOOSE_EDITABLE ? 3 : 0;
  379.     
  380.     c->listbox = listbox_new (1, 1, cols-2, lines-button_lines,
  381.                listbox_finish, 0);
  382.     
  383.     if (button_lines){
  384.     add_widget (c->dialog, button_new (lines-button_lines+1,
  385.                     20, B_ENTER, "[ Remove ]", 'r', 2,
  386.                     remove_callback, c));
  387.     add_widget (c->dialog, button_new (lines-button_lines+1,
  388.                     4, B_CANCEL, "[ Cancel ]", 'c', 2, 0, 0));
  389.     }            
  390.     add_widget (c->dialog, c->listbox);
  391.     return c;
  392. }
  393.  
  394. int run_chooser (Chooser *c)
  395. {
  396.     run_dlg (c->dialog);
  397.     return c->dialog->ret_value;
  398. }
  399.  
  400. void destroy_chooser (Chooser *c)
  401. {
  402.     destroy_dlg (c->dialog);
  403. }
  404.  
  405. /* }}} */
  406.  
  407. /* {{{ Quick dialog routines */
  408.  
  409. static int quick_callback (struct Dlg_head *h, int id, int Msg)
  410. {
  411.     switch (Msg){
  412. #ifndef HAVE_X    
  413.     case DLG_DRAW:
  414.     attrset (REVERSE_COLOR);
  415.     dlg_erase (h);
  416.     draw_box (h, 1, 1, h->lines-2, h->cols-2);
  417.     
  418.     attrset (COLOR_HOT_NORMAL);
  419.     dlg_move (h, 1, 2);
  420.     printw (h->data);
  421.     break;
  422.  
  423.     case DLG_KEY:
  424.     if (id == '\n'){
  425.         h->running = 0;
  426.         h->ret_value = B_ENTER;
  427.         break;
  428.     }
  429. #endif    
  430.     }
  431.     return 0;
  432. }
  433.  
  434. int quick_dialog_skip (QuickDialog *qd, int nskip)
  435. {
  436.     Dlg_head *dd;
  437.     void     *widget;
  438.     WRadio   *r;
  439.     int      xpos;
  440.     int      ypos;
  441.     int      return_val;
  442.     WInput   *input;
  443.     QuickWidget *qw;
  444.     
  445.     if (qd->xpos == -1)
  446.         dd = create_dlg (0, 0, qd->ylen, qd->xlen, dialog_colors, quick_callback,
  447.                  qd->help, qd->class, DLG_CENTER | DLG_TRYUP);
  448.     else
  449.         dd = create_dlg (qd->ypos, qd->xpos, qd->ylen, qd->xlen, dialog_colors, 
  450.                          quick_callback,
  451.                  qd->help, qd->class, 0);
  452.  
  453.     x_set_dialog_title (dd, qd->title);
  454.     
  455.     /* We pass this to the callback */
  456.     dd->cols  = qd->xlen;
  457.     dd->lines = qd->ylen;
  458.     dd->data  = qd->title;
  459.  
  460.     for (qw = qd->widgets; qw->widget_type; qw++){
  461. #ifndef HAVE_X
  462.     xpos = (qd->xlen * qw->relative_x)/qw->x_divisions;
  463.     ypos = (qd->ylen * qw->relative_y)/qw->y_divisions;
  464. #endif
  465.     
  466.     if (!qw->tk_frame)
  467.         tk_end_frame ();
  468.     else
  469.         tk_new_frame (dd, qw->tk_frame);
  470.     
  471.     switch (qw->widget_type){
  472.     case quick_checkbox:
  473.         widget = check_new (ypos, xpos, *qw->result, qw->text,
  474.                 qw->hotkey, qw->hotkey_pos);
  475.         break;
  476.  
  477.     case quick_radio:
  478.         r = radio_new (ypos, xpos, qw->hotkey, qw->str_result, 1);
  479.         r->pos = r->sel = qw->value;
  480.         widget = r;
  481.         break;
  482.         
  483.     case quick_button:
  484.         widget = button_new (ypos, xpos, qw->value, qw->text,
  485.                 qw->hotkey, qw->hotkey_pos, 0, 0);
  486.         break;
  487.  
  488.         /* We use the hotkey pos as the field length */
  489.     case quick_input:
  490.         input = input_new (ypos, xpos, INPUT_COLOR,
  491.                    qw->hotkey_pos, qw->text);
  492.         input->is_password = qw->value == 1;
  493.         input->point = 0;
  494.         if (qw->value & 2)
  495.             input->completion_flags |= INPUT_COMPLETE_CD;
  496.         widget = input;
  497.         break;
  498.  
  499.     case quick_label:
  500.         widget = label_new (ypos, xpos, qw->text);
  501.         break;
  502.         
  503.     default:
  504.         widget = 0;
  505.         fprintf (stderr, "QuickWidget: unknown widget type\n");
  506.         break;
  507.     }
  508.     qw->the_widget = widget;
  509.     add_widgetl (dd, widget, qw->layout);
  510.     }
  511.  
  512.     while (nskip--)
  513.     dd->current = dd->current->next;
  514.  
  515.     run_dlg (dd);
  516.  
  517.     /* Get the data if we found something interesting */
  518.     if (dd->ret_value != B_CANCEL){
  519.     for (qw = qd->widgets; qw->widget_type; qw++){
  520.         switch (qw->widget_type){
  521.         case quick_checkbox:
  522.         *qw->result = ((WCheck *) qw->the_widget)->state & C_BOOL;
  523.         break;
  524.  
  525.         case quick_radio:
  526.         *qw->result = ((WRadio *) qw->the_widget)->sel;
  527.         break;
  528.         
  529.         case quick_input:
  530.         *qw->str_result = strdup (((WInput *) qw->the_widget)->buffer);
  531.         break;
  532.         }
  533.     }
  534.     }
  535.     return_val = dd->ret_value;
  536.     destroy_dlg (dd);
  537.     
  538.     return return_val;
  539. }
  540.  
  541. int quick_dialog (QuickDialog *qd)
  542. {
  543.     return quick_dialog_skip (qd, 0);
  544. }
  545.  
  546. /* }}} */
  547.  
  548. /* {{{ Input routines */
  549. #define INPUT_INDEX 2
  550. char *input_dialog_help (char *header, char *text, char *help, char *def_text)
  551. {
  552.     QuickDialog Quick_input;
  553.     QuickWidget quick_widgets [] = {
  554.     { quick_button, 6, 10, 1, 0, "[ Cancel ]", 'c', 2, B_CANCEL, 0, 0,
  555.       XV_WLAY_DONTCARE, "b." },
  556.     { quick_button, 3, 10, 1, 0, "[ Ok ]", 'o', 2, B_ENTER, 0, 0,
  557.       XV_WLAY_DONTCARE, "" },
  558.     { quick_input,  4, 80, 0, 0, 0, 0, 58, 0, 0, 0, XV_WLAY_BELOWCLOSE, 0 },
  559.     { quick_label,  3, 80, 2, 0, 0, 0, 0, 0, 0, 0, XV_WLAY_DONTCARE, 0 },
  560.     { 0 } };
  561.     
  562.     int len;
  563.     int i;
  564.     int lines;
  565.     char *my_str;
  566.     
  567.     len = max (strlen (header), msglen (text, &lines)) + 4;
  568.     len = max (len, 64);
  569.  
  570.     if (strncmp (text, "Password", 8) == 0){
  571.     quick_widgets [INPUT_INDEX].value = 1;
  572.     } else {
  573.     quick_widgets [INPUT_INDEX].value = 0;
  574.     }
  575.     
  576.     Quick_input.xlen  = len;
  577.     Quick_input.xpos  = -1;
  578.     Quick_input.title = header;
  579.     Quick_input.help  = help;
  580.     Quick_input.class = "quick_input";
  581.     quick_widgets [INPUT_INDEX+1].text = text;
  582.     quick_widgets [INPUT_INDEX].text = def_text;
  583.  
  584.     for (i = 0; i < 4; i++)
  585.     quick_widgets [i].y_divisions = lines+6;
  586.     Quick_input.ylen  = lines + 6;
  587.  
  588.     for (i = 0; i < 3; i++)
  589.     quick_widgets [i].relative_y += 2 + lines;
  590.  
  591.     quick_widgets [INPUT_INDEX].str_result = &my_str;
  592.     
  593.     Quick_input.widgets = quick_widgets;
  594.     if (quick_dialog (&Quick_input) != B_CANCEL){
  595.     return *(quick_widgets [INPUT_INDEX].str_result);
  596.     } else
  597.     return 0;
  598. }
  599.  
  600. char *input_dialog (char *header, char *text, char *def_text)
  601. {
  602.     return input_dialog_help (header, text, "[Input Line Keys]", def_text);
  603. }
  604.  
  605. char *input_expand_dialog (char *header, char *text, char *def_text)
  606. {
  607.     char *result;
  608.     char *expanded;
  609.  
  610.     result = input_dialog (header, text, def_text);
  611.     if (result){
  612.     expanded = tilde_expand (result);
  613.     if (expanded){
  614.         free (result);
  615.         return expanded;
  616.     } else 
  617.         return result;
  618.     }
  619.     return result;
  620. }
  621.  
  622. /* }}} */
  623.  
  624. /*
  625.   Cause emacs to enter folding mode for this file:
  626.   Local variables:
  627.   end:
  628. */
  629.